package Thread;

class MyBlockingQueue {

    private String[] queue = null;

    private int size; // 记录数组元素个数
    private int head; // 队首元素
    private int tail; // 队尾元素

    public MyBlockingQueue(int capacity) {
        this.queue = new String[capacity];
    }

    Object locker = new Object();

    public void put(String elem) throws InterruptedException {
        // 其实锁加到这里，就和加到方法上没什么区别了
        synchronized (locker) {
            while (size >= queue.length) {
                // 如果队列已满，就要进入阻塞等待状态
                // 等待队列有坑位之后，再执行
                locker.wait();
            }

            // 插入元素
            queue[tail] = elem;
            tail++;

            // 如果tail已经走到数组末尾，就要重新回到开头
            if (tail >= queue.length) {
                tail = 0;
            }
            size++;
            // 入队列成功后，唤醒要出队列的线程
            locker.notify();
        }
    }

    public String take() throws InterruptedException {
        String old = null;
        synchronized (locker) {
            // 拿取元素，要判断队列里面是否有元素，如果为空，则阻塞等待
            while (size == 0) {
                locker.wait();
            }
            // 拿取元素
            old = queue[head];
            head++;
            //如果head走到数组末尾，重新回到数组开头
            if (head >= queue.length) {
                head = 0;
            }
            size--;
            // 出队列后，唤醒入队列的线程
            // 这个情况出现在：生产者消费者模型中，生产速度与消费速度不一致，导致的线程阻塞
            locker.notify();
        }
        return old;
    }

}
public class ThreadDemo22 {

    public static void main(String[] args) throws InterruptedException {
        MyBlockingQueue queue = new MyBlockingQueue(100);
        /*queue.put("aaa");
        queue.put("bbb");
        queue.put("ccc");
        queue.put("ddd");

        String a = queue.take();
        System.out.println(a);

        a = queue.take();
        System.out.println(a);

        a = queue.take();
        System.out.println(a);

        a = queue.take();
        System.out.println(a);

        a = queue.take();
        System.out.println(a);*/

        Thread t1 = new Thread(() -> {
            int n = 1;
            while (true) {
                try {
                    queue.put(n + "");
                    System.out.println("生产个数：" + n);
                    n++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while (true) {
                try {
                    System.out.println("消费个数：" + queue.take());
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        t1.start();
        t2.start();
    }


}
